// 这里书写 taobao 项目的打包内容

// 0. 导入 gulp 第三方模块
const gulp = require('gulp')
// 0-1. 导入 gulp-cssmin 第三方模块, 用于压缩 css 文件
const cssmin = require('gulp-cssmin')
// 0-1-1. 导入 gulp-autoprefixer 第三方模块, 用于自动添加前缀
const autoprefixer = require('gulp-autoprefixer')
// 0-4. 导入 gulp-uglify 第三方, 用于把 js 代码压缩
const uglify = require('gulp-uglify')
// 0-5. 导入 gulp-babel 第三方, 用于把 ES6 转换成 ES5
const babel = require('gulp-babel')
// 0-6. 导入 gulp-sass
const sass = require('gulp-sass')(require('sass'))
// 0-7. 导入 gulp-htmlmin
const htmlmin = require('gulp-htmlmin')
// 0-8. 导入 gulp-imagemin
// const imagemin = require('gulp-imagemin')
// 0-9. 导入 del
const del = require('del')
// 0-10. 导入 gulp-webserver
const webserver = require('gulp-webserver')
/*
1. 配置打包 css 的任务
    + 如何打包 css 文件 ?
    + 有一个第三方包, 专门用来去除 css 文件中的空格的
    + 叫做 gulp-cssmin
    + 下载: $ npm i -D gulp-cssmin
    + 导入: const cssmin = require('gulp-cssmin')
    + 导入以后得到的是一个函数, 直接调用就可以了
    + 在 gulpfile 内把 cssHandler 这个任务进行导出
    => 导出以后, 就可以在命令行利用 gulp 工具来执行这个任务了
    => 打开命令行, 目录切换到项目根目录
    => 输入指令: $ gulp 任务名称
    + 解决一个报错:
    => 因为 gulp 工具捕获不到 cssHandler 任务的完成
    => 并不是不能完成, 只是 gulp 不知道他什么时候完成的
    => 因为 gulp 工具没有得到 gulp 的工作流
    => 只要写一个 return 就可以了

扩展: 自动添加前缀
    + 问题: 压缩之前做, 还是之后做 ?
    => 先找到文件, 自动添加前缀, 把添加完前缀的压缩
    + 自动添加前缀有一个第三方包
    => 叫做 gulp-autoprefixer
    => 下载: $ npm i -D gulp-autoprefixer
    => 导入: const autoprefixer = require('gulp-autoprefixer')
    => 导入以后: 就会得到一个函数, 直接调用执行就能自动添加前缀
        -> 但是需要传递一个参数, 表示你要兼容的是哪些浏览器
    + 执行的时候会有警告提示, 解决问题
    => 原因: 不推荐在使用插件的时候传递参数
        -> 推荐放在配置文件内
        -> { browsers: ['', ''] }
    => 解决: 把配置项以 browserslist 字段写在 package.json 内
*/

// 1-1. 创建一个 打包 css 的任务
// 问题: 打包 css 和 打包 js 有没有可能是一样的 ?
// 打包一种文件, 就需要一个任务
// 将来你执行 cssHandler 的时候, 就是在执行对应的函数
// const cssHandler = () => {
//     // 1-2. 找到源文件
//     // 你要打包的是 ./src/js 文件夹里面的内容吗 ?
//     // 你要打包的是 ./src/images 文件夹里面的内容吗 ?
//     // 不一定 , 所以需要你书写确定打包的是哪里面的内容
//     // 注意 : 在配置任务的时候, 把工作流 return 出去
//     return gulp
//         .src('./src/css/*.css') // 找到原始文件
//         .pipe(autoprefixer()) // 自动添加前缀
//         .pipe(cssmin()) // 进行 css 代码的压缩打包
//         .pipe(gulp.dest('./dist/css/')) // 放到指定目录内
// }

/*
2. 打包 js 文件
+ 创建任务函数
+ 导出 : 在函数内配置打包 js 的过程
=> 获取到你要打包的 js 文件
=> 进行压缩
=> 放到指定的路径内
+ 如何压缩 js 代码 :
+ 压缩 js 文件需要使用一个第三方包, 叫做 gulp-uglify
+ 下载: $ npm i -D gulp-uglify
+ 导入: const uglify = require('gulp-uglify')
+ 导入以后, 得到一个函数, 直接调用执行就可以对 js 代码进行压缩了
=> 注意: js 内书写 ES6 及以上的语法
-> 不会进行转码, 原样打包
如何把 ES6 转换为 ES5 
+ 问题: 什么时候进行转码操作 ?
=> 找到文件之后, 先进行转码, 再进行压缩
+ 使用一个第三方包进行转换, 叫做  gulp-babel
=> 注意: 因为 gulp-babel 的运行需要依赖另外两个包
-> 但是他自己不会下载
-> 需要我们手动把另外两个包也下载下来
-> 一个叫做 @babel/core 的包
-> 一个叫做 @babel/preset-env 的包
+ 下载:
=> $ npm i -D gulp-babel
=> $ npm i -D @babel/core
=> $ npm i -D @babel/preset-env
+ 导入: const babel = require('gulp-babel')
+ 导入以后, 得到的就是一个函数, 调用执行函数的时候传递参数就可以进行 es6 转换 es5 了
-> 使用的时候需要传递一个参数
=> 传递的参数是一个 { presets: ['@babel/preset-env'] }

总结: 对于 js 的打包任务
=> 如果你只是想打包, 不需要 ES6 转码
    -> 下载 gulp-uglify, 直接导入使用
=> 如果你想 ES6 转码
+ 下载:
=> gulp-uglify   用于压缩
=> gulp-babel    用于转码
=> @babel/core   用于 babel 依赖
=> @babel/preset-env  用于 babel 依赖
+ 导入:
=> const uglify = require('gulp-uglify')
=> const babel = require('gulp-babel')
+ 使用:
=> uglify()
=> babel({ presets: ['@babel/preset-env'] })
*/

// 3-1. 创建一个 打包 js 文件的任务
const jsHandler = () => {
    // 3-2. 找到指定的 js 文件
    return gulp
        .src('./src/js/*.js') // 找到指定的 js 文件
        .pipe(babel({ presets: ['@babel/preset-env'] })) // 进行 ES6 转换 ES5
        .pipe(uglify()) // 对 js 代码进行压缩
        .pipe(gulp.dest('./dist/js/')) // 放到指定目录内
}

/*
3. 打包 sass 的任务
+ 和 打包 css 的任务有什么区别 ?
=> 就多了一个过程, 就是把 sass 转换成 css
+ 准备一个 sass 的任务函数
+ 导出 :
+ 在函数内进行打包 sass 任务的配置转换
=> 获取到指定 sass 文件
=> 先把 sass 语法转换成 css 语法
=> 然后自动添加前缀
=> 然后压缩 css 文件代码
=> 然后放在一个指定的目录内
+ 如何把 sass 转换成 css
+ 需要用到一个第三方包, 叫做 gulp-sass
=>  特别说明 :
-> 当你下载 gulp-sass 的时候, 大概率会失败
-> 因为 gulp-sass 这个第三方依赖了一个叫做 node-sass 的第三方包
在你下载 gulp-sass 的时候, 会自动下载 node-sass 这个第三方包
+ node-sass 这个第三方在 npm 上是一个 压缩包(zip), 下载以后需要 在系统里把压缩包 解压 完
-> 所以就会导致 node-sass 的下载很容易失败
-> 最后 gulp-sass 还需要依赖一个叫做  sass  的包 (下载指令: $ npm i -D sass )
-> 解决:
    + 手动下载 node-sass 使用单独的下载地址
    + 有人做了把 node-sass 转换成和其他的包一样的状态
    + 在下载 gulp-sass 之前, 我们临时设置一个下载地址
    + 打开命令行, 输入指令: $ set SASS_BINARY_PATH=D:\win32-x64-57_binding.node
    + 然后再次尝试下载
=> 导入的时候
-> const sass = require('gulp-sass')(require('sass'))
-> 导入以后, 得到一个函数, 直接调用就能把 sass 转换成 css 文件

总结: 最新版本的 gulp-sass 包 5.x
    + 下载:
    => $ npm i -D gulp-sass
    => $ npm i -D node-sass
    => $ npm i -D sass
    + 下载 node-sass 会大概率失败
    => 下载失败的时候, 执行下面这句代码
    => 临时把 node-sass 的下载地址切换 ( 单独切换一个包的下载地址 )
    => $ set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/
    => 再次尝试下载就好了
    + 导入:
    => 只需要导入一个 gulp-sass
    => 语法: const sass = require('gulp-sass')(require('sass'))
    + 使用:
    => sass()
*/

// 2-1. 创建一个打包 sass 文件的任务
const sassHandler = () => {
    // 2-2. 找到指定的文件
    return gulp
        .src('./src/sass/*.scss')       // 找到需要编译的 sass 文件 
        .pipe(sass())                   // 进行 sass 转换成 css 的操作
        .pipe(autoprefixer())           // 给 css 代码自动添加前缀
        .pipe(cssmin())                 // 对 css 代码进行压缩处理
        .pipe(gulp.dest('./dist/css/'))// 放在指定目录下
}

/*
4. 打包 html 的任务
    + 压缩 html 需要用到一个第三方包, 叫做 gulp-htmlmin
    + 下载: $ npm i -D gul-htmlmin
    + 导入: const htmlmin = require('gulp-htmlmin')
    + 导入以后得到一个函数, 直接调用, 需要传递参数来实现
    => 如果你不传递参数, 不会进行任何压缩操作
*/
// 4-1. 创建一个打包 html 文件的任务
const htmlHandler = () => {
    // 4-2. 找到指定的文件
    return gulp
        .src('./src/views/*.html')
        .pipe(htmlmin({
            // 去掉所有的空格空白内容
            collapseWhitespace: true,
            // 去掉布尔类型属性
            collapseBooleanAttributes: true,
            // 移出属性值位置的双引号
            removeAttributeQuotes: true,
            // 移出注释内容
            removeComments: true,
            // 移出空属性
            removeEmptyAttributes: true,
            // 移出 script 标签上的默认 type 属性
            removeScriptTypeAttributes: true,
            // 移出 style 标签和 link 标签的 默认 type 属性
            removeStyleLinkTypeAttributes: true,
            // 压缩内嵌式 js 代码
            // 注意: 不能包含 es6 语法
            minifyJS: true,
            // 压缩内嵌式 css 样式
            minifyCSS: true
        })) // 进行压缩
        .pipe(gulp.dest('./dist/views/')) // 放到指定目录
}


/*
5. 打包 images 的任务
    + 压缩图片需要使用一个第三方包叫做 gulp-imagemin
    + 下载: $ npm i -D gulp-imagemin
    + 导入: const imagemin = require('gulp-imagemin')
*/

// 5-1. 创建一个打包 image 的任务
// const imgHandler = () => {
//     // 5-2. 找到指定内容
//     return gulp
//         .src('./src/images/*.**')
//         .pipe(imagemin())
//         .pipe(gulp.dest('./dist/images/'))
// }
// 6. 配置一个转移 img 文件的任务
const imgHandler = () => {
    return gulp
        .src('./src/images/**/*')
        .pipe(gulp.dest('./dist/images/'))
}
/*
6. 一些内容的转移任务
    + 遇到视音频都是直接转移
*/
const audioHandler = () => {
    return gulp
        .src('./src/audios/*.**')
        .pipe(gulp.dest('./dist/audio/'))
}

const videoHandler = () => {
    return gulp
        .src('./src/videos/*.**')
        .pipe(gulp.dest('./dist/videos/'))
}

// fonts 直接转移
const fontHandler = () => {
    return gulp
        .src('./src/fonts/*.**')
        .pipe(gulp.dest('./dist/fonts/'))
}

// data 直接转移
const dataHandler = () => {
    return gulp
        .src('./src/data/*.**')
        .pipe(gulp.dest('./dist/data/'))
}

// vendor 直接转移
const vendorHandler = () => {
    return gulp
        .src('./src/vendor/*.**')
        .pipe(gulp.dest('./dist/vendor/'))
}

/*
7. 配置一个 删除 dist 文件的任务
    + 删除文件夹需要用到一个第三方包叫做 del
    + 下载: $ npm i -D del
    + 导入: const del = require('del')
    + 导入以后得到的就是一个 函数
    => 直接调用 del(['要删除的文件夹名称'])
    + 需要把这个任务加到 默认任务中
    => 是否需要和其他任务有顺序关系
*/

const delHandler = () => {
    return del(['./dist/'])
}

/*
8. 配置一个启动临时服务器的任务
    + 配置启动服务器需要用到一个包叫做 gulp-webserver
    + 下载: $ npm i -D gulp-webserver
    + 导入: const webserver = requrie('gulp-webserver')
    + 导入以后得到一个函数, 需要配置一些信息
    + 问题: 如果你打开页面查看, 应该是看 dist 里面的html 文件
            还是查看 src 目录下的 html 文件
*/
// const serverHandler = () => {
//     // 找到目录
//     return gulp
//         .src('./dist/')
//         .pipe(webserver({  // 开启服务器
//             // 域名
//             host: 'localhost',
//             // 端口号
//             port: 8080,
//             // 默认自动打开哪一个文件, 路径从 dist 以后开始书写就行
//             open: './views/index.html',
//             // 自动刷新, 当代码发生变化的时候, 自动刷新浏览器
//             livereload: true,
//             // 配置服务器代理
//             proxies: [
//                 // 一个代理就是一个对象
//                 {
//                     // 代理标识符
//                     source: '/guoxiang',
//                     // 目标地址
//                     target: 'http://localhost:8080/test.php'
//                 }
//             ]
//         }))
// }

/*
webserver 的时候, host 位置可以书写自定义域名
    1. host 确定好你要用的域名(尽量不要用一些大众的域名)
    2. 进行 系统 hosts 文件的配置
    => OS: command + g -> 输入 /etc 回车
    => win: 我的电脑 -> 系统盘符 -> windows -> system32 -> drivers -> etc
    => 找到一个叫做 hosts 的文件(注意这个文件只有名字没有后缀)
*/


/*
9. 配置一个监控任务
    + 当文件发生变化的时候, 能够从新执行进行打包操作
*/

// const watchHandler = () => {
//     // 用于监控变化
//     // gulp.watch('./src/css/*.css', cssHandler)
//     gulp.watch('./src/sass/*.sass', sassHandler)
//     gulp.watch('./src/views/*.html', htmlHandler)
//     gulp.watch('./src/js/*.js', jsHandler)
// }

/*
倒是第二. 配置一个默认任务
    + 作用: 能帮我把其他任务调动起来
*/

// 创建一个默认任务
// 需要把其他的一些任务一起执行掉
// 使用 gulp.parallel 来实现并行
// 语法: gulp.parallel(任务1, 任务2, 任务3, ...)
// 返回值, 就是一个函数, 直接赋值给 _default
const res = gulp.parallel(sassHandler, jsHandler, htmlHandler, imgHandler, videoHandler, audioHandler, dataHandler, fontHandler, vendorHandler)

// 当你导出了一个任务叫做 default 的时候
// 你在使用 gulp default 这个指令的时候
// 可以简写, 直接写 gulp
// 默认会自动执行一个叫做 default 的 任务
const _default = gulp.series(
    delHandler,
    res
    // serverHandler,
    // watchHandler
)

// end, 把准备好的任务导出
module.exports = {
    // cssHandler: cssHandler,
    jsHandler: jsHandler,
    sassHandler: sassHandler,
    htmlHandler: htmlHandler,
    imgHandler: imgHandler,
    audioHandler: audioHandler,
    videoHandler: videoHandler,
    fontHandler: fontHandler,
    dataHandler: dataHandler,
    vendorHandler: vendorHandler,
    delHandler: delHandler,
    default: _default,
}
